//
//  GCD_Queue_Group_VC.m
//  DXC
//
//  Created by MC on 2017/6/2.
//  Copyright © 2017年 TOPTEAM. All rights reserved.
//

#import "GCD_Queue_Group_VC.h"
#import "GCDQG_view.h"

@interface GCD_Queue_Group_VC ()
<
GCDQG_Delegate
>
@property (nonatomic,strong)GCDQG_view * viewQG;
@end

@implementation GCD_Queue_Group_VC
/*
 * 队列组的简单使用: 监听任务的完成
 
 所有的任务会并发的执行(不按序)
 所有的异步函数, 都是添加到队列中, 然后再纳入到队列组的监听范围
 使用dispatch_group_notify(队列组, 队列)函数, 来监听在这个函数上面的任务执行是否完成, 当任务完成, 就会调用这个方法
 
 */
- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor=[UIColor whiteColor];
    
    
    
    /*
     * 1、简单方式（从Xib加载UIView比较原始的方法）
     
     这种方式仅仅适用于只有一个视图并且没有任何其他交互绑定。除了对Cocoa的初学阶段比较有容易理解之外，这种方式真的没有什么特别的优势
     
     首先使用[NSBundle loadNibNamed:owner:options]方法，只带第一个参数。
     
     只要把以下代码放到你控制器（Controller）的 implementation块里面；
     */
    
    
    // Instantiate the nib content without any reference to it.
    
    NSArray *nibContents = [[NSBundle mainBundle] loadNibNamed:@"GCDQG_view" owner:nil options:nil];
    
    // Find the view among nib contents (not too hard assuming there is only one view in it).
    
    UIView *plainView = [nibContents lastObject];
    
    // Some hardcoded layout.
    
    CGSize padding = (CGSize){ 22.0, 22.0 };
    
    plainView.frame = (CGRect){padding.width, padding.height, plainView.frame.size};
    

    _viewQG=(GCDQG_view *)plainView;
    __weak typeof(self) weakSelf = self;

    _viewQG.block = ^(NSInteger t) {
        if (t==1) {
            [weakSelf test1];
        }else if(t==2){
            [weakSelf test2];
        }
    };
    _viewQG.delegate=self;
    [self.view addSubview:plainView];
    

}


/*
 * 队列组的简单使用: 监听任务的完成
 * 所有的任务会并发的执行(不按序)
 * 所有的异步函数, 都是添加到队列中, 然后再纳入到队列组的监听范围
 * 使用dispatch_group_notify(队列组, 队列)函数, 来监听在这个函数上面的任务执行是否完成, 当任务完成, 就会调用这个方法
 */
-(void)test1{
    // 1. 创建队列组
    dispatch_group_t group = dispatch_group_create();
    
    // 2. 创建并发队列
    dispatch_queue_t queue = dispatch_queue_create("123", DISPATCH_QUEUE_CONCURRENT);
    
    // 3. 使用函数添加任务
    dispatch_group_async(group, queue, ^{
        sleep(1);
        NSLog(@"1---%@", [NSThread currentThread]);
    });
    
    dispatch_group_async(group, queue, ^{
        NSLog(@"2---%@", [NSThread currentThread]);
    });
    
    dispatch_group_async(group, queue, ^{
        sleep(2);
        NSLog(@"3---%@", [NSThread currentThread]);
    });
    
    dispatch_group_async(group, queue, ^{
        NSLog(@"4---%@", [NSThread currentThread]);
    });
    
    // 4. 让队列组监听任务的完成
    dispatch_group_notify(group, queue, ^{
        NSLog(@"执行完毕");
    });

}

/*
 * 队列组和函数对
 * 队列组的函数对用法是目前比较少见的用法, 这个用法比较老, 好处是严格的控制/监听了每个进入队列组的任务
 * 该方法只能使用异步函数
 * 基本步骤:
 
 * 首先要使用队列组创建函数, 创建一个队列组
 * 创建一个并发队列
 * 开启队列组, 然后使用异步函数封装每一个任务
 * 当任务执行结束之后, 要将加入到队列组的任务移除队列组(类似于引用计数管理, 计数+1必须伴随计数-1) + 队列组通常与dispatch_group_wait连用, 等待队列组中的任务X秒, 之后再继续执行后面的任务
 */
-(void)test2{
    // 1. 获取队列组
    dispatch_group_t group = dispatch_group_create();
    
    // 2. 创建队列
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    
    // 3. 队列组开启 -- 将下面的任务纳入队列组中
    dispatch_group_enter(group);
    // 4. 使用异步函数封装任务
    dispatch_async(queue, ^{
        NSLog(@"1---%@", [NSThread currentThread]);
        // 5. 确保任务结束之后，让该任务离开队列组
        dispatch_group_leave(group);
    });
    
    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        sleep(1);
        NSLog(@"2---%@", [NSThread currentThread]);
        dispatch_group_leave(group);
    });
    
    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        NSLog(@"3---%@", [NSThread currentThread]);
        dispatch_group_leave(group);
    });
    
    // 拦截通知
    dispatch_group_notify(group, queue, ^{
        NSLog(@"任务结束");
    });
    
    // 同步执行，等待队列组time的时间后执行后面的代码，如果队列组中的任务都完成了，就返回0，如果没完成，就返回非0值
    dispatch_time_t timer = dispatch_time(DISPATCH_TIME_NOW, 0.00000002 * NSEC_PER_SEC);
    
    // 等待tiemr秒的时间，不管队列中任务是否完成，都继续往下执行，如果改时间内任务完成了就返回0，否则是非零值
    long n = dispatch_group_wait(group, timer);
    NSLog(@"%ld", n);
    
    NSLog(@"----end------");
}
-(void)action_test3{
    
}



- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end
